package cn.assumejson.springframework.context.context.annotation;

import cn.assumejson.springframework.beans.PropertyValue;
import cn.assumejson.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import cn.assumejson.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import cn.assumejson.springframework.beans.factory.support.BeanDefinitionRegistry;
import cn.assumejson.springframework.beans.factory.support.DefaultListableBeanFactory;
import cn.assumejson.springframework.beans.factory.support.RootBeanDefinition;

import java.beans.Introspector;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 配置注解启动
 *
 * @author Mr. Li
 * @version 1.0
 * @since 1.0 2021/12/3 12:39
 */
public class AnnotationConfigUtils {

    /**
     * The bean name of the internally managed Configuration annotation processor.
     */
    public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
            "cn.assumejson.springframework.context.context.annotation.internalConfigurationAnnotationProcessor";


    /**
     * The bean name of the internally managed Autowired annotation processor.
     */
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
            "cn.assumejson.springframework.beans.factory.annotation.internalAutowiredAnnotationBeanPostProcessor";

    /**
     * 解析配置文件
     */
    public static final String PROPERTY_PLACEHOLDER_ANNOTATION_PROCESSOR_BEAN_NAME =
            "cn.assumejson.springframework.beans.factory.config.internalPropertyPlaceholderConfigurer";


    /**
     * AOP
     */
    public static final String ASPECTJ_AUTO_PROXY_REGISTRAR_BEAN_NAME =
            "cn.assumejson.springframework.context.context.annotation.internalAspectJAutoProxyRegistrar";

    /**
     * 注册 该配置类
     *
     * @param registry
     */
    public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, null);
    }

    private static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source) {
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (null != beanFactory) {
        }

        // 收集所有创世纪类
        Set<RootBeanDefinition> beanDefs = new LinkedHashSet<>(8);

        /*
         注册@Configrition注解
         */
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            // 设置 beanFactory
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }


        /*
         * 为我们容器中注册了处理@Autowired 注解的处理器AutowiredAnnotationBeanPostProcessor
         * 名字叫:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
         */
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            // 设置 beanFactory
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(PROPERTY_PLACEHOLDER_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
//            PropertyValue propertyValue = new PropertyValue("location", "classpath:token.properties");
//            def.getPropertyValues().addPropertyValue(propertyValue);
            // 解析配置类
            beanDefs.add(registerPostProcessor(registry, def, PROPERTY_PLACEHOLDER_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

    }

    private static RootBeanDefinition registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
        return registry.registerBeanDefinition(beanName, definition);
    }

    private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
        if (registry instanceof DefaultListableBeanFactory) {
            return (DefaultListableBeanFactory) registry;
        } else {
            return null;
        }
    }
}
